package be.gnx.logging4eclipse.perspective.widget;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Caret;
import org.eclipse.swt.widgets.Composite;

import be.gnx.logging4eclipse.perspective.model.logging.Event;

public class LoggingEntryWidget extends ScrolledComposite {

  private StyledText styledText;

  public LoggingEntryWidget(Composite parent, int style) {
    super (parent, style | SWT.H_SCROLL | SWT.V_SCROLL);
    setAlwaysShowScrollBars(false);
    setExpandVertical(true);
    setExpandHorizontal(true);

    Composite composite = new Composite(this, SWT.NONE);
    composite.setLayout(new FillLayout());
    setContent(composite);

    styledText = new StyledText(composite, SWT.MULTI | SWT.READ_ONLY);
    composite.setBackground(styledText.getBackground());

    Caret caret = new Caret(styledText, SWT.NONE);
    caret.setVisible(false);
    styledText.setCaret(caret);

    addDisposeListener(new DisposeListener() {
      public void widgetDisposed(DisposeEvent disposeEvent) {
        LoggingEntryWidget.this.widgetDisposed(disposeEvent);
      }
    });

    addControlListener(new ControlAdapter() {
      @Override
      public void controlResized(ControlEvent controlEvent) {
        LoggingEntryWidget.this.controlResized(controlEvent);
        // super.controlResized(controlEvent);
      }
    });

  }

  private void widgetDisposed(DisposeEvent disposeEvent) {
    dispose();
  }

  private void controlResized(ControlEvent controlEvent) {
    resize();
  }

  @Override
  public void dispose() {
    
  }

  private void resize() {
    
  }

  public void setLoggingEvent(Event loggingEvent) {
    List<TextWithStyle> content = toContent(loggingEvent);
    styledText.setText(toString(content));
    styledText.setStyleRanges(toStyleRanges(content));
    styledText.pack(true);
    setMinSize(styledText.getSize());
  }

  private List<TextWithStyle> toContent(Event loggingEvent) {
    List<TextWithStyle> textWithStyleList = new ArrayList<TextWithStyle>();
    textWithStyleList.add(new TextWithStyle("Location: ", styledText.getBackground(), styledText.getForeground(), SWT.ITALIC | SWT.BOLD));
    textWithStyleList.add(new TextWithStyle(loggingEvent.getLocation().toString() + "\n", styledText.getBackground(), styledText.getForeground(), SWT.NONE));
    textWithStyleList.add(new TextWithStyle("Message: ", styledText.getBackground(), styledText.getForeground(), SWT.ITALIC | SWT.BOLD));
    textWithStyleList.add(new TextWithStyle(loggingEvent.getMessage().toString() + "\n\n", styledText.getBackground(), styledText.getForeground(), SWT.NONE));
    if (loggingEvent.getStackTrace() != null) {
      textWithStyleList.add(new TextWithStyle("StackTrace:\n", styledText.getBackground(), styledText.getForeground(), SWT.ITALIC | SWT.BOLD));
      textWithStyleList.add(new TextWithStyle(loggingEvent.getStackTrace().toString(), styledText.getBackground(), styledText.getForeground(), SWT.NONE));
    }
    return textWithStyleList;
  }

  private class TextWithStyle {

    String text;

    Color background;

    Color foreground;

    int fontStyle;

    public TextWithStyle(String text, Color background, Color foreground,
        int fontStyle) {
      this.text = text;
      this.background = background;
      this.foreground = foreground;
      this.fontStyle = fontStyle;
    }

  }

  public static String toString(List<TextWithStyle> textWithStyleList) {
    StringBuffer stringBuffer = new StringBuffer("");
    for (TextWithStyle textWithStyle : textWithStyleList) {
      stringBuffer.append(textWithStyle.text);
    }
    return stringBuffer.toString();
  }

  public static StyleRange[] toStyleRanges(List<TextWithStyle> textWithStyleList) {
    StyleRange[] styleRanges = new StyleRange[textWithStyleList.size()];
    int index = 0;
    int start = 0;
    for (TextWithStyle textWithStyle : textWithStyleList) {
      int length = textWithStyle.text.length();
      styleRanges[index] = new StyleRange(start, length,
          textWithStyle.foreground, textWithStyle.background,
          textWithStyle.fontStyle);
      index++;
      start = start + length;
    }
    return styleRanges;
  }

}
